package top.juc.plugin.idea.openfeignx.provider;

import com.intellij.util.ReflectionUtil;
import top.juc.plugin.idea.openfeignx.annotation.Annotation;
import top.juc.plugin.idea.openfeignx.util.CacheUtils;
import top.juc.plugin.idea.openfeignx.util.JavaUtils;
import top.juc.plugin.idea.openfeignx.util.SpringMvcUtils;
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo;
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider;
import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.util.IconLoader;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import org.apache.commons.lang3.ObjectUtils;
import org.jetbrains.annotations.NotNull;

import java.util.Collection;
import java.util.Optional;

import static top.juc.plugin.idea.openfeignx.util.Icons.IMAGES_FEIGN_SVG;

/**
 * The type Mapper line marker provider.
 *
 * @author yanglin
 *
 * 1. 类有注解 @RestController
 * 2. 项目名称, 如:spring.application.name
 * 3. 拼接contoller.id: spring.application.name + @RestController.value + 方法(@PostMappin.value | @GetMapping.value | @PutMapping.value | @DeleteMapping.value | @RequestMapping.value)
 * 3. 找到所有 @FeignClient 注解的类
 * 4. 拼接feign.id: @FeignClient.name + @FeignClient.path + 方法(@PostMappin.value | @GetMapping.value | @PutMapping.value | @DeleteMapping.value | @RequestMapping.value)
 *
 *
 */
public class ControllerLineMarkerProvider extends RelatedItemLineMarkerProvider {
    private static final Logger LOG = Logger.getInstance(ControllerLineMarkerProvider.class);


    @Override
    protected void collectNavigationMarkers(@NotNull PsiElement element, @NotNull Collection<? super RelatedItemLineMarkerInfo<?>> result) {
        if (!(element instanceof PsiClass)) {
            return;
        }
        PsiClass clazz = (PsiClass) element;
        if (!isTargetClass(clazz)) {
            return;
        }

        CacheUtils.clearClass(element.getProject(), Annotation.REST_CONTROLLER, clazz);

        // method方法的类包含 @RestController 注解
        // 通过PsiMethod 找到 PsiClass
        String projectName = CacheUtils.getModuleSpringApplicationName(clazz);
        String prefixPath = JavaUtils.getAnnotationValueText(clazz, Annotation.REQUEST_MAPPING).orElse("");
        for (PsiMethod method : clazz.getMethods()) {
            String fullPath = SpringMvcUtils.getFullPath(projectName, prefixPath, SpringMvcUtils.getMethodPath(method));
            CacheUtils.setMethod(element.getProject(), Annotation.REST_CONTROLLER, fullPath, method);
            PsiMethod psiMethod = CacheUtils.getMethod(element.getProject(), Annotation.FEIGN_CLIENT, fullPath);

            if(ObjectUtils.isEmpty(psiMethod)){
                continue;
            }
            NavigationGutterIconBuilder<PsiElement> builder =
                NavigationGutterIconBuilder.create(IconLoader.getIcon(IMAGES_FEIGN_SVG, this.getClass()))
                    .setAlignment(GutterIconRenderer.Alignment.CENTER)
                    .setTarget(psiMethod)
                    .setTooltipTitle("Feign - " + Optional.ofNullable(psiMethod.getContainingClass()).map(PsiClass::getQualifiedName).orElse("") + "#" + psiMethod.getName());
            result.add(builder.createLineMarkerInfo(method.getNameIdentifier()));

        }
    }

    private boolean isTargetClass(PsiClass clazz) {
        return JavaUtils.isAnnotationPresent(clazz, Annotation.REST_CONTROLLER)
            && JavaUtils.isAnnotationPresent(clazz, Annotation.REQUEST_MAPPING);
    }
}
